import 'dart:async';
import 'dart:typed_data';

import 'package:dartx/dartx.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:sgy_flutter/ble/packet.dart';

abstract class BaseService {
  final String _serviceGuid;
  final String? _characteristicWriteGuid;
  final String? _characteristicReadGuid;
  final String? _characteristicNotifyGuid;

  BaseService(
      {required String serviceGuid,
      required String? characteristicWriteGuid,
      required String? characteristicReadGuid,
      required String? characteristicNotifyGuid})
      : _serviceGuid = serviceGuid,
        _characteristicWriteGuid = characteristicWriteGuid,
        _characteristicReadGuid = characteristicReadGuid,
        _characteristicNotifyGuid = characteristicNotifyGuid;

  BluetoothCharacteristic? readCharacteristic;
  BluetoothCharacteristic? writeCharacteristic;
  BluetoothCharacteristic? notifyCharacteristic;

  StreamController<List<int>> _streamController = StreamController.broadcast();

  Stream<List<int>> get stream =>
      _streamController.stream.where((test) => test.isNotEmpty);


  bool get isSupportNotify => notifyCharacteristic != null;

  /**
   * 初始化服务
   */
  Future<List<StreamSubscription>> initializeService(
      List<BluetoothService> services) async {
    List<StreamSubscription> list = List.empty(growable: true);
    for (final service in services) {
      if (service.uuid.str128.toLowerCase() == _serviceGuid) {
        for (final characteristic in service.characteristics) {
          final characteristicGuid = characteristic.uuid.str128.toLowerCase();
          if (characteristicGuid == _characteristicWriteGuid) {
            writeCharacteristic = characteristic;
          }
          if (characteristicGuid == _characteristicReadGuid) {
            readCharacteristic = characteristic;
          }
          if (characteristicGuid == _characteristicNotifyGuid) {
            notifyCharacteristic = characteristic;
            final subscription =
                characteristic.onValueReceived.listen((value) async {
              _streamController.sink.add(value);

              await handleNotifyData(Uint8List.fromList(value));
            });

            list.add(subscription);
            await characteristic.setNotifyValue(true);
          }
        }
      }
    }
    await onInitialized(services);
    print("服务初始化:${runtimeType } notifyCharacteristic:$notifyCharacteristic");
    print("服务初始化:${runtimeType } writeCharacteristic:$writeCharacteristic");
    print("服务初始化:${runtimeType } readCharacteristic:$readCharacteristic");
    return list;
  }

  /**
   * 清理服务
   */
  Future cleanup() async {
    _streamController.sink.add([]);
    notifyCharacteristic = null;
    writeCharacteristic = null;
    readCharacteristic = null;
    _cacheData.clear();
    await onCleanup();
  }

  FutureOr handleNotifyData(Uint8List data) {}

  FutureOr handlePacketData(Packet data) {}

  Future onInitialized(List<BluetoothService> services) async {}

  Future onCleanup() async {}

  List<int> _cacheData = List.empty(growable: true);

  StreamTransformer<List<int>, Packet> packetStreamTransformer() {
    return StreamTransformer.fromHandlers(handleData: (data, sink) {
      try {
        final byteData = Uint8List.fromList(data).buffer.asByteData();
        final fromHeader = [byteData.getUint8(0), byteData.getUint8(1)];
        if (fromHeader.contentEquals(Packet.header)) {
          _cacheData.clear();
        }
        _cacheData.addAll(data);
        final packet = Packet.fromBleData(Uint8List.fromList(_cacheData));
        _cacheData.clear();
        sink.add(packet);
      } catch (e) {
        print("packetStreamTransformer:${e}");
      }
    });
  }
}
